package org.jeecg.modules.flowable.service.action.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.Execution;
import org.flowable.task.api.Task;
import org.jeecg.modules.flowable.common.util.IdUtil;
import org.jeecg.modules.flowable.common.util.validation.MustParamValidation;
import org.jeecg.modules.flowable.dic.MatterFlowStatus;
import org.jeecg.modules.flowable.entity.TActMatterInstEntity;
import org.jeecg.modules.flowable.entity.TActTheendEntity;
import org.jeecg.modules.flowable.exception.ModuleFlowableException;
import org.jeecg.modules.flowable.mapper.TActMatterInstMapper;
import org.jeecg.modules.flowable.mapper.TActTheendMapper;
import org.jeecg.modules.flowable.service.FlowProcService;
import org.jeecg.modules.flowable.service.FlowableService;
import org.jeecg.modules.flowable.service.action.ActionBody;
import org.jeecg.modules.flowable.service.action.ActionExec;
import org.jeecg.modules.flowable.system.core.SystemUser;
import org.jeecg.modules.flowable.system.etc.SystemUserUtil;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Title: 回退致发起者 <br>
 * Desc:  <br>
 * Date: 6/26/22 10:03 AM <br>
 * Company: 联通（辽宁）产业互联网有限公司 <br>
 *
 * @author zxd
 * @version 1.0.0
 */
@Service("BackToInitiate")
@Slf4j
public class BackToInitiate implements ActionExec {
    @Autowired
    private FlowProcService flowProcService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private TActTheendMapper tActTheendMapper;

    @Autowired
    private TActMatterInstMapper tActMatterInstMapper;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deal(ActionBody argActionBody, String argActionFunname, String argActionFuncode) {
        MustParamValidation.mustValidation(argActionBody.getMatterInstId(), argActionBody.getTaskId());
        SystemUser loginUser = SystemUserUtil.getSystemUser();
        DateTime now = DateTime.now();
        // 第一步：保存
        flowProcService.save(argActionBody.getMatterInstId(), argActionBody.getTaskId(), argActionBody.getAttType(), argActionBody.getAttDesc(), argActionBody.getFormData(), argActionBody.getAttrList(), argActionFunname, argActionFuncode, argActionBody.getFormContent());
        // 第二步：查找END节点，结束流程
        List<Task> list = taskService.createTaskQuery().taskId(argActionBody.getTaskId()).list();
        String procDefId = list.get(0).getProcessDefinitionId();
        String procInstId = list.get(0).getProcessInstanceId();
        Process mainProcess = repositoryService.getBpmnModel(procDefId).getMainProcess();
        Collection<FlowElement> flowElements = mainProcess.getFlowElements();
        FlowElement flowElement = flowElements.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList()).get(0);
        // 查询当前执行流
        List<Execution> list1 = runtimeService.createExecutionQuery().parentId(procInstId).list();
        List<String> collect = list1.stream().map(Execution::getActivityId).collect(Collectors.toList());

        // 第三步，执行到最后
        runtimeService.createChangeActivityStateBuilder().processInstanceId(procInstId).moveActivityIdsToSingleActivityId(collect, flowElement.getId()).changeState();
        // 第四步 回写流程结果表
        TActMatterInstEntity matterinstEn = tActMatterInstMapper.selectById(argActionBody.getMatterInstId());
        Boolean flowFinish = flowableService.isFlowFinish(matterinstEn.getProcInstId());
        if (flowFinish) {
            TActTheendEntity tActTheendEntity = new TActTheendEntity().setId(IdUtil.getStringId()).setCreateBy(loginUser.getRealname()).setCreateTime(now.toDate()).setUpdateBy(loginUser.getRealname()).setUpdateTime(now.toDate()).setDelFlag(0);
            tActTheendEntity.setAcceptId(loginUser.getId());
            tActTheendEntity.setAcceptName(loginUser.getRealname());
            tActTheendEntity.setEndTime(now.toDate());
            tActTheendEntity.setLastAttType(argActionBody.getAttType());
            tActTheendEntity.setProcInstId(matterinstEn.getProcInstId());
            tActTheendEntity.setTaskId(argActionBody.getTaskId());
            tActTheendMapper.insert(tActTheendEntity);
        } else {
            throw new ModuleFlowableException("流程中止失败，原因是任务处理节没有完全结束");
        }
        // 第五步 回写事项实例表
        LambdaQueryWrapper<TActMatterInstEntity> qq = new LambdaQueryWrapper<>();
        qq.eq(TActMatterInstEntity::getId, argActionBody.getMatterInstId());
        TActMatterInstEntity inst = tActMatterInstMapper.selectList(qq).get(0);
        TActMatterInstEntity tActMatterInstEntity = new TActMatterInstEntity();
        tActMatterInstEntity.setEndTime(now.toDate());
        tActMatterInstEntity.setStatus(MatterFlowStatus.UNDO);
        tActMatterInstEntity.setCostTime(now.toDate().getTime() - inst.getStartTime().getTime());
        tActMatterInstMapper.update(tActMatterInstEntity, qq);
        return true;
    }
}